/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
import { computed, defineComponent, ref } from 'vue';
import { IResourceViewModel, ITaskViewModel } from '../../interface';
import useStore, { initStore } from '../../store';
import {
  useDrag,
  useVirtualScroll,
  useInitScheduleTable,
  useScheduleTableReSize,
  useScheduleTableStyle,
  useScheduleTableEvent,
} from '../../hooks';
import { ScheduleTableEvent, ScheduleTableProps } from './schedule-table-type';
import {
  useScheduleToolbarEvent,
  useScheduleTableDataUpdate,
} from '../../hooks/use-schedule-table';
import { ScheduleToolbar } from '../schedule-toolbar/schedule-toolbar';
import './schedule-table.scss';

export const ScheduleTable = defineComponent({
  name: 'ScheduleTable',
  components: {
    'schedule-toolbar': ScheduleToolbar,
  },
  props: ScheduleTableProps,
  emits: ScheduleTableEvent,
  setup(props, { emit, slots }) {
    // 头部canvas实例
    const headerCanvas = ref<HTMLCanvasElement | null>(null);

    // 内容canvas实例
    const bodyCanvas = ref<HTMLCanvasElement | null>(null);

    // 坐标元素
    const coordinateElement = ref<HTMLDivElement | null>(null);

    // 任务拖拽阴影
    const taskGhost = ref<HTMLDivElement | null>(null);

    // 初始化store
    initStore(props, emit as any);

    const { $config, $renderLayer } = useStore();

    const config = $config.getConfig();

    const resources = $renderLayer.getResources();

    // 初始化表格
    const { resourceViewModels, taskViewModels } = useInitScheduleTable(
      headerCanvas,
      bodyCanvas,
      coordinateElement,
    );

    useScheduleTableDataUpdate(props, coordinateElement);

    // 处理工具栏事件
    const { onDataRefresh, onSave, onSaveAs, onConfigRefresh } =
      useScheduleToolbarEvent(coordinateElement);

    // 处理表格事件
    const {
      handleResourceContextMenu,
      handleTaskContextMenu,
      handleCellContextMenu,
      handleResourceClick,
      handleTaskClick,
      handleCellClick,
      selectedTaskId,
    } = useScheduleTableEvent(bodyCanvas);

    // 计算表格样式
    const { headerStyle, bodyStyle, calcTaskStyle } = useScheduleTableStyle(
      props,
      slots && !!slots.extraToolbar,
    );

    // 监听视图大小变化
    useScheduleTableReSize(props, headerCanvas, bodyCanvas, coordinateElement);

    // 虚拟滚动
    const { visibleRange, handleScroll } = useVirtualScroll(coordinateElement);

    // 拖拽
    const { handleDrop, handleDragOver, handleDragLeave } = useDrag(
      props,
      coordinateElement,
      bodyCanvas,
      taskGhost,
    );

    // 过滤可见的资源
    const visibleResourceViewModels = computed(() => {
      if (!resourceViewModels.value) return [];
      return resourceViewModels.value.slice(
        visibleRange.value.start,
        visibleRange.value.end,
      );
    });

    // 过滤可见的任务
    const visibleTaskViewModels = computed(() => {
      if (!taskViewModels.value) return [];
      return taskViewModels.value.filter((task: ITaskViewModel) => {
        const resourceIndex = resources.findIndex(
          res => res.id === task.resourceId,
        );
        return (
          resourceIndex >= visibleRange.value.start &&
          resourceIndex < visibleRange.value.end
        );
      });
    });

    return {
      config,
      bodyStyle,
      taskGhost,
      bodyCanvas,
      headerStyle,
      headerCanvas,
      visibleRange,
      selectedTaskId,
      coordinateElement,
      visibleTaskViewModels,
      visibleResourceViewModels,
      calcTaskStyle,
      onSave,
      onSaveAs,
      handleDrop,
      handleScroll,
      onDataRefresh,
      handleDragOver,
      handleDragLeave,
      onConfigRefresh,
      handleResourceContextMenu,
      handleTaskContextMenu,
      handleCellContextMenu,
      handleResourceClick,
      handleTaskClick,
      handleCellClick,
    };
  },
  render() {
    return (
      <div class='schedule-table'>
        <div class='schedule-toolbar-area'>
          <div class='schedule-toolbar'>
            <div class='schedule-table-title' title={this.caption}>
              {this.caption}
            </div>
            <schedule-toolbar
              onSave={this.onSave}
              onSaveAs={this.onSaveAs}
              toolarModel={this.toolarModel}
              onRefresh={this.onDataRefresh}
              onConfigChange={this.onConfigRefresh}
            ></schedule-toolbar>
          </div>
          {this.$slots.extraToolbar ? (
            <div class='schedule-toolbar-extra'>
              {this.$slots.extraToolbar()}
            </div>
          ) : null}
        </div>
        <div class='schedule-table-header' style={this.headerStyle}>
          <canvas
            ref='headerCanvas'
            class='schedule-bg-layer schedule-table-header-canvas'
          ></canvas>
        </div>
        <div
          ref='coordinateElement'
          class='schedule-table-body'
          style={this.bodyStyle}
          onDrop={this.handleDrop}
          onScroll={this.handleScroll}
          onDragover={this.handleDragOver}
          onDragleave={this.handleDragLeave}
        >
          <canvas
            ref='bodyCanvas'
            class='schedule-bg-layer schedule-table-body-canvas'
            onClick={event => this.handleCellClick(event)}
            onContextmenu={event => this.handleCellContextMenu(event)}
          ></canvas>
          <div class='schedule-task-layer'>
            {this.visibleResourceViewModels.length > 0 ? (
              <>
                {this.visibleResourceViewModels.map(
                  (resourceViewModel: IResourceViewModel) => {
                    return (
                      <div
                        class='absolute-item resource-item'
                        data-resource-id={resourceViewModel.id}
                        style={{
                          width: `${resourceViewModel.width}px`,
                          height: `${resourceViewModel.height}px`,
                          top: `${resourceViewModel.top}px`,
                          left: `${resourceViewModel.left}px`,
                        }}
                        onClick={event =>
                          this.handleResourceClick(resourceViewModel, event)
                        }
                        onContextmenu={event =>
                          this.handleResourceContextMenu(
                            resourceViewModel,
                            event,
                          )
                        }
                      >
                        {this.$slots.resourceItem
                          ? this.$slots.resourceItem(resourceViewModel.data)
                          : resourceViewModel.data.name}
                      </div>
                    );
                  },
                )}
              </>
            ) : null}
            {this.visibleTaskViewModels.length > 0 ? (
              <>
                {this.visibleTaskViewModels.map(
                  (taskViewModel: ITaskViewModel) => {
                    const { taskColor, taskBgColor, taskAcitveBorderColor } =
                      this.calcTaskStyle(taskViewModel);
                    return (
                      <div
                        data-task-id={taskViewModel.id}
                        data-resource-id={taskViewModel.resourceId}
                        data-origin-task-id={taskViewModel.originalId}
                        style={{
                          width: `${taskViewModel.width}px`,
                          height: `${taskViewModel.height}px`,
                          top: `${taskViewModel.top}px`,
                          left: `${taskViewModel.left}px`,
                          color: taskColor,
                          backgroundColor: taskBgColor,
                          borderColor:
                            taskViewModel.originalId === this.selectedTaskId
                              ? taskAcitveBorderColor
                              : undefined,
                        }}
                        class={{
                          'task-item': true,
                          'absolute-item': true,
                          'task-resizable': taskViewModel.dragEdge !== 'none',
                          'is-selected':
                            taskViewModel.originalId === this.selectedTaskId,
                        }}
                        onClick={event =>
                          this.handleTaskClick(taskViewModel, event)
                        }
                        onContextmenu={event =>
                          this.handleTaskContextMenu(taskViewModel, event)
                        }
                      >
                        {['top', 'default'].includes(taskViewModel.dragEdge) &&
                          this.config.allowDrag && (
                            <div class='resize-handle resize-top'></div>
                          )}
                        {this.taskSlotLimit.minWidth < taskViewModel.width &&
                          this.taskSlotLimit.minHeight <
                            taskViewModel.height && (
                            <div class='task-item-content'>
                              {this.$slots.taskItem
                                ? this.$slots.taskItem(taskViewModel.data)
                                : taskViewModel.data.name}
                            </div>
                          )}
                        {['bottom', 'default'].includes(
                          taskViewModel.dragEdge,
                        ) &&
                          this.config.allowDrag && (
                            <div class='resize-handle resize-bottom'></div>
                          )}
                      </div>
                    );
                  },
                )}
              </>
            ) : null}
            <div ref='taskGhost' class='task-ghost'>
              <div class='start-time'></div>
              <div class='end-time'></div>
            </div>
          </div>
        </div>
      </div>
    );
  },
});
